{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<!--BOOK_INFORMATION-->\n",
    "<img align=\"left\" style=\"padding-right:10px;\" src=\"fig/cover-small.jpg\">\n",
    "*This notebook contains an excerpt from the [Whirlwind Tour of Python](http://www.oreilly.com/programming/free/a-whirlwind-tour-of-python.csp) by Jake VanderPlas; the content is available [on GitHub](https://github.com/jakevdp/WhirlwindTourOfPython).*\n",
    "\n",
    "*The text and code are released under the [CC0](https://github.com/jakevdp/WhirlwindTourOfPython/blob/master/LICENSE) license; see also the companion project, the [Python Data Science Handbook](https://github.com/jakevdp/PythonDataScienceHandbook).*\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<!--NAVIGATION-->\n",
    "< [Generators](12-Generators.ipynb) | [Contents](Index.ipynb) | [String Manipulation and Regular Expressions](14-Strings-and-Regular-Expressions.ipynb) >"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Modules and Packages"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "One feature of Python that makes it useful for a wide range of tasks is the fact that it comes \"batteries included\" – that is, the Python standard library contains useful tools for a wide range of tasks.\n",
    "On top of this, there is a broad ecosystem of third-party tools and packages that offer more specialized functionality.\n",
    "Here we'll take a look at importing standard library modules, tools for installing third-party modules, and a description of how you can make your own modules."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Loading Modules: the ``import`` Statement\n",
    "\n",
    "For loading built-in and third-party modules, Python provides the ``import`` statement.\n",
    "There are a few ways to use the statement, which we will mention briefly here, from most recommended to least recommended."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Explicit module import\n",
    "\n",
    "Explicit import of a module preserves the module's content in a namespace.\n",
    "The namespace is then used to refer to its contents with a \"``.``\" between them.\n",
    "For example, here we'll import the built-in ``math`` module and compute the cosine of pi:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-1.0"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import math\n",
    "math.cos(math.pi)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Explicit module import by alias\n",
    "\n",
    "For longer module names, it's not convenient to use the full module name each time you access some element.\n",
    "For this reason, we'll commonly use the \"``import ... as ...``\" pattern to create a shorter alias for the namespace.\n",
    "For example, the NumPy (Numerical Python) package, a popular third-party package useful for data science, is by convention imported under the alias ``np``:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-1.0"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "np.cos(np.pi)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Explicit import of module contents\n",
    "\n",
    "Sometimes rather than importing the module namespace, you would just like to import a few particular items from the module.\n",
    "This can be done with the \"``from ... import ...``\" pattern.\n",
    "For example, we can import just the ``cos`` function and the ``pi`` constant from the ``math`` module:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-1.0"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from math import cos, pi\n",
    "cos(pi)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Implicit import of module contents\n",
    "\n",
    "Finally, it is sometimes useful to import the entirety of the module contents into the local namespace.\n",
    "This can be done with the \"``from ... import *``\" pattern:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.0"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from math import *\n",
    "sin(pi) ** 2 + cos(pi) ** 2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This pattern should be used sparingly, if at all.\n",
    "The problem is that such imports can sometimes overwrite function names that you do not intend to overwrite, and the implicitness of the statement makes it difficult to determine what has changed.\n",
    "\n",
    "For example, Python has a built-in ``sum`` function that can be used for various operations:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on built-in function sum in module builtins:\n",
      "\n",
      "sum(...)\n",
      "    sum(iterable[, start]) -> value\n",
      "    \n",
      "    Return the sum of an iterable of numbers (NOT strings) plus the value\n",
      "    of parameter 'start' (which defaults to 0).  When the iterable is\n",
      "    empty, return start.\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(sum)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can use this to compute the sum of a sequence, starting with a certain value (here, we'll start with ``-1``):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "9"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sum(range(5), -1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now observe what happens if we make the *exact same function call* after importing ``*`` from ``numpy``:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "from numpy import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sum(range(5), -1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The result is off by one!\n",
    "The reason for this is that the ``import *`` statement *replaces* the built-in ``sum`` function with the ``numpy.sum`` function, which has a different call signature: in the former, we're summing ``range(5)`` starting at ``-1``; in the latter, we're summing ``range(5)`` along the last axis (indicated by ``-1``).\n",
    "This is the type of situation that may arise if care is not taken when using \"``import *``\" – for this reason, it is best to avoid this unless you know exactly what you are doing."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Importing from Python's Standard Library\n",
    "\n",
    "Python's standard library contains many useful built-in modules, which you can read about fully in [Python's documentation](https://docs.python.org/3/library/).\n",
    "Any of these can be imported with the ``import`` statement, and then explored using the help function seen in the previous section.\n",
    "Here is an extremely incomplete list of some of the modules you might wish to explore and learn about:\n",
    "\n",
    "- ``os`` and ``sys``: Tools for interfacing with the operating system, including navigating file directory structures and executing shell commands\n",
    "- ``math`` and ``cmath``: Mathematical functions and operations on real and complex numbers\n",
    "- ``itertools``: Tools for constructing and interacting with iterators and generators\n",
    "- ``functools``: Tools that assist with functional programming\n",
    "- ``random``: Tools for generating pseudorandom numbers\n",
    "- ``pickle``: Tools for object persistence: saving objects to and loading objects from disk\n",
    "- ``json`` and ``csv``: Tools for reading JSON-formatted and CSV-formatted files.\n",
    "- ``urllib``: Tools for doing HTTP and other web requests.\n",
    "\n",
    "You can find information on these, and many more, in the Python standard library documentation: https://docs.python.org/3/library/."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Importing from Third-Party Modules\n",
    "\n",
    "One of the things that makes Python useful, especially within the world of data science, is its ecosystem of third-party modules.\n",
    "These can be imported just as the built-in modules, but first the modules must be installed on your system.\n",
    "The standard registry for such modules is the Python Package Index (*PyPI* for short), found on the Web at http://pypi.python.org/.\n",
    "For convenience, Python comes with a program called ``pip`` (a recursive acronym meaning \"pip installs packages\"), which will automatically fetch packages released and listed on PyPI (if you use Python version 2, ``pip`` must be installed separately).\n",
    "For example, if you'd like to install the ``supersmoother`` package that I wrote, all that is required is to type the following at the command line:\n",
    "```\n",
    "$ pip install supersmoother\n",
    "```\n",
    "The source code for the package will be automatically downloaded from the PyPI repository, and the package installed in the standard Python path (assuming you have permission to do so on the computer you're using).\n",
    "\n",
    "For more information about PyPI and the ``pip`` installer, refer to the documentation at http://pypi.python.org/."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<!--NAVIGATION-->\n",
    "< [Generators](12-Generators.ipynb) | [Contents](Index.ipynb) | [String Manipulation and Regular Expressions](14-Strings-and-Regular-Expressions.ipynb) >"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
